#ifndef BOOST_BASE64_STREAM_HPP_INCLUDED
#define BOOST_BASE64_STREAM_HPP_INCLUDED

#include <sstream>

#include <boost/io/detail/bin_manip.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/istream_range.hpp>

#include "base64_converter.hpp"

struct base64_stream
{
	std::stringstream sstream_;

	//~base64_stream()
	//{
	//	1 == 1;
	//}


	//friend base64_stream& operator<<( 	base64_stream& b64, const char *_Val)
	template <typename OutputStreamable>
	friend base64_stream& operator<<( base64_stream & b64,  OutputStreamable const& _Val )
	{
		b64.sstream_ << _Val;
		return b64;
	}

	template <typename InputStreamable>
	friend base64_stream& operator>>( base64_stream & b64,  InputStreamable & _Val )
	{
		b64.sstream_ >> _Val;
		return b64;
	}

	friend std::ostream& operator<<( std::ostream & ostr, base64_stream & b64 )
	{
		using boost::base64_encoder;
		using boost::base64_decoder;
		using boost::adaptors::converted;
		using boost::istream_range;

		

 		//boost::copy( istream_range<char>(b64.sstream_) | converted(base64_encoder()),
			//		 std::ostream_iterator<char>(std::cout) 
		 // 		   );

		std::string temp = b64.sstream_.str();

 		//boost::copy( temp | converted(base64_encoder()),
			//		 std::ostream_iterator<char>(std::cout) 
		 // 		   );


 		//boost::copy( istream_range<char>(b64.sstream_) | converted(base64_encoder()),
			//		 std::ostream_iterator<char>(ostr) 
		 // 		   );

 		boost::copy( temp | converted(base64_encoder()),
					 std::ostream_iterator<char>(ostr) 
		  		   );

		return ostr;
	}

	friend std::istream& operator>>( std::istream & istr, base64_stream & b64 )
	{
		using boost::base64_encoder;
		using boost::base64_decoder;
		using boost::adaptors::converted;
		using boost::istream_range;

 		boost::copy( istream_range<char>(istr) | converted(base64_decoder()),
					 std::ostream_iterator<char>(b64.sstream_) 
		  		   );

		return istr;
	}


	friend std::ostream& operator<<=( std::ostream & ostr, base64_stream & b64 )
	{
		return operator<<(ostr, b64);
	}

	//friend std::istream& operator>>( std::istream& istr, base64_stream const& data )
	//{
	//	return istr;
	//}
};


#endif // BOOST_BASE64_STREAM_HPP_INCLUDED